package org.jeecg.modules.demo.Kingdee.Job;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.kingdee.bos.webapi.sdk.K3CloudApi;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * 更新金蝶应付单到期日的定时任务类
 * 
 * 功能：查询并更新应付单中到期日字段为空的数据
 * 查询条件：
 * 1. 到期日字段FINISHDATE为空
 * 2. 开票核销状态为完全：FOPENSTATUS='C'
 * 3. 付款条件为月结、双月结、三月结：FPAYCONDITON IN (20002,2147447,2147448)
 * 4. 付款核销状态为完全核销：FWRITTENOFFSTATUS='A'
 * 
 * 更新逻辑：
 * 将到期日字段FINISHDATE更新为：F_RBPB_Integer（年月格式，如202510）+ FPAYCONDITON.FName对应的账期月数
 * 然后取该月的最后一天作为到期日
 * 
 * 工作流程：
 * 1. 查询符合条件的应付单列表
 * 2. 遍历每条记录，根据规则计算新的到期日
 * 3. 更新每条记录的FINISHDATE字段
 */
@Slf4j
@Component
public class KDUpdatePayableFinishDateJob implements Job {

    /**
     * 定时任务执行方法
     * 
     * @param jobExecutionContext 定时任务执行上下文
     * @throws Exception 执行过程中可能抛出的异常
     */
    @SneakyThrows
    @Override
    public void execute(JobExecutionContext jobExecutionContext) {
        try {
            // 查询需要更新到期日的应付单列表
            queryAndUpdateFinishDate();
            
        } catch (Exception e) {
            log.error("执行更新应付单到期日任务时发生错误: ", e);
        }
    }
    
    /**
     * 查询并更新应付单的到期日字段
     */
    private void queryAndUpdateFinishDate() {
        try {
            // 构造查询条件
            // 1. 到期日字段FINISHDATE为空
            // 2. 开票核销状态为完全：FOPENSTATUS='C'
            // 3. 付款条件为月结、双月结、三月结：FPAYCONDITON IN (20002,2147447,2147448)
            // 4. 付款核销状态为完全核销：FWRITTENOFFSTATUS='A'
            String filterString = "FINISHDATE IS NULL AND FOPENSTATUS='C' AND FPAYCONDITON IN (20002,2147447,2147448) AND FWRITTENOFFSTATUS='A'";
            
            // 设置查询字段
            String fieldKeys = "FID,FBillNo,FINISHDATE,F_RBPB_Integer,FPAYCONDITON.FName";
            
            // 构造查询JSON
            String queryJson = String.format(
                "{\"FormId\":\"AP_Payable\",\"FieldKeys\":\"%s\",\"FilterString\":\"%s\",\"OrderString\":\"\",\"TopRowCount\":0,\"StartRow\":0,\"Limit\":2000}",
                fieldKeys, filterString
            );
            
            log.info("开始查询金蝶应付单，查询条件: {}", filterString);
            
            // 初始化K3CloudApi并执行查询
            K3CloudApi api = new K3CloudApi();
            String resultStr = api.billQuery(queryJson);
            
            // 解析查询结果
            List<JSONObject> resultList = JSONArray.parseArray(resultStr, JSONObject.class);
            
            log.info("应付单查询完成，共找到 {} 条需要更新到期日的应付单记录", resultList.size());
            
            // 处理查询结果并更新到期日
            int updateCount = 0;
            for (JSONObject item : resultList) {
                try {
                    String billId = item.getString("FID");
                    String billNo = item.getString("FBillNo");
                    String rbpbInteger = item.getString("F_RBPB_Integer");
                    String payCondition = item.getString("FPAYCONDITON.FName");
                    
                    log.info("处理应付单 - 单据ID: {}, 单据编号: {}, 年月字段: {}, 付款条件: {}", 
                        billId, billNo, rbpbInteger, payCondition);
                    
                    // 计算新的到期日
                    String newFinishDate = calculateFinishDate(rbpbInteger, payCondition);
                    if (newFinishDate != null) {
                        // 更新到期日字段
                        boolean updateResult = updateFinishDate(billId, newFinishDate);
                        if (updateResult) {
                            updateCount++;
                            log.info("成功更新应付单 {} 的到期日为: {}", billNo, newFinishDate);
                        }
                    }
                } catch (Exception e) {
                    log.error("处理应付单 {} 时发生错误: ", item.getString("FBillNo"), e);
                }
            }
            
            log.info("任务执行完成，共更新 {} 条应付单记录", updateCount);
            
        } catch (Exception e) {
            log.error("查询并更新应付单到期日时发生错误: ", e);
        }
    }
    
    /**
     * 根据年月字段和付款条件计算到期日
     * 
     * @param rbpbInteger 年月字段，格式如202510
     * @param payCondition 付款条件名称，如"月结30天"、"月结60天"、"月结90天"
     * @return 计算后的到期日，格式为yyyy-MM-dd
     */
    private String calculateFinishDate(String rbpbInteger, String payCondition) {
        try {
            if (rbpbInteger == null || rbpbInteger.isEmpty() || payCondition == null || payCondition.isEmpty()) {
                log.warn("年月字段或付款条件为空，无法计算到期日");
                return null;
            }
            
            // 解析年月字段
            if (rbpbInteger.length() != 6) {
                log.warn("年月字段格式不正确: {}", rbpbInteger);
                return null;
            }
            
            String yearStr = rbpbInteger.substring(0, 4);
            String monthStr = rbpbInteger.substring(4, 6);
            
            int year = Integer.parseInt(yearStr);
            int month = Integer.parseInt(monthStr);
            
            // 根据付款条件确定需要增加的月数和需要往前推的天数
            int addMonths = 0;
            int subtractDays = 0;
            if (payCondition.contains("月结30天")) {
                addMonths = 1; // 加1个月
                subtractDays = 3; // 往前推3天
            } else if (payCondition.contains("月结60天")) {
                addMonths = 2; // 加2个月
                subtractDays = 5; // 往前推5天
            } else if (payCondition.contains("月结90天")) {
                addMonths = 3; // 加3个月
                subtractDays = 7; // 往前推7天
            } else {
                log.warn("不支持的付款条件: {}", payCondition);
                return null;
            }
            
            // 计算目标年月
            LocalDate baseDate = LocalDate.of(year, month, 1);
            LocalDate targetDate = baseDate.plusMonths(addMonths);
            
            // 获取目标月份的最后一天
            YearMonth yearMonth = YearMonth.from(targetDate);
            LocalDate lastDay = yearMonth.atEndOfMonth();
            
            // 根据账期天数往前推相应的天数
            LocalDate finishDate = lastDay.minusDays(subtractDays);
            
            // 格式化为字符串
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            return finishDate.format(formatter);
            
        } catch (Exception e) {
            log.error("计算到期日时发生错误，年月字段: {}, 付款条件: {}", rbpbInteger, payCondition, e);
            return null;
        }
    }
    
    /**
     * 更新应付单的到期日字段
     * 
     * @param billId 应付单ID
     * @param finishDate 新的到期日
     * @return 更新是否成功
     */
    private boolean updateFinishDate(String billId, String finishDate) {
        try {
            // 构造更新JSON，参考UpdateTicketStatusJob.java中的格式
            String updateJson = String.format(
                "{\n" +
                "\"NeedUpDateFields\": [\n" +
                "\"FINISHDATE\"\n" +
                "],\n" +
                "\"IsDeleteEntry\": \"true\",\n" +
                "\"Model\": {\n" +
                "\"FID\": %s,\n" +
                "\"FINISHDATE\": \"%s\"\n" +
                "}\n" +
                "}",
                billId, finishDate
            );
            
            log.debug("准备更新应付单，更新JSON: {}", updateJson);
            
            // 初始化K3CloudApi并执行更新
            K3CloudApi api = new K3CloudApi();
            String resultStr = api.save("AP_Payable", updateJson);
            
            log.debug("更新结果: {}", resultStr);
            
            // 简单解析结果（根据实际API返回格式调整）
            JSONObject result = JSONObject.parseObject(resultStr);
            if (result != null && result.containsKey("Result")) {
                JSONObject resultObj = result.getJSONObject("Result");
                if (resultObj != null && resultObj.containsKey("ResponseStatus")) {
                    JSONObject responseStatus = resultObj.getJSONObject("ResponseStatus");
                    if (responseStatus != null && responseStatus.getBoolean("IsSuccess")) {
                        return true;
                    }
                }
            }
            
            log.warn("更新应付单到期日失败，单据ID: {}, 结果: {}", billId, resultStr);
            return false;
            
        } catch (Exception e) {
            log.error("更新应付单到期日时发生错误，单据ID: {}", billId, e);
            return false;
        }
    }
}